/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.wryproject.slice;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.colors.RgbPalette;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayoutManager;
import ohos.agp.components.Image;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Slider;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.element.VectorElement;
import ohos.agp.utils.Color;
import ohos.agp.window.service.WindowManager;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;

import com.example.wryproject.ResourceTable;
import com.example.wryproject.database.MusicData;
import com.example.wryproject.database.PlayingIndex;
import com.example.wryproject.provider.MusicListProvider;
import com.example.wryproject.service.MusicServiceAbility;
import com.example.wryproject.utils.DatabaseUtils;
import com.example.wryproject.utils.LogUtil;
import com.example.wryproject.utils.ThreadUtil;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @since 2021-08-05
 */
public class MusicAbilitySlice extends AbilitySlice implements MusicServiceAbility.PlayCallback {
    private static AbilitySlice context;
    private static List<MusicData> musicDataList;
    private ListContainer listContainer;
    private static Button btLast;
    private static Button btPlay;
    private static Button btNext;
    private static Image fixed;
    private Image musicCover;
    private static Text currentDuration;
    private static Slider slider;
    private static EventHandler eventHandler;
    private static int updateValue;
    private static MusicListProvider provider;
    private Timer timer;
    private Text totalDuration;
    private Text number;
    private Text playerAll;
    private Text title;
    private Text singerName;
    private MusicServiceAbility.MusicRemoteObject musicRemoteObject;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        setUIContent(ResourceTable.Layout_music);
        context = this;

        musicRemoteObject = MusicServiceAbility.get();
        if (musicRemoteObject == null) {
            startService();
        }
        while (musicRemoteObject == null) {
            musicRemoteObject = MusicServiceAbility.get();
            LogUtil.debug("WRYCHH", "get");
        }
        initLayout();
        listClickEvent();
        playListener();
        //沉浸式状态栏
        getWindow().addFlags(WindowManager.LayoutConfig.MARK_TRANSLUCENT_STATUS);
    }

    @Override
    protected void onActive() {
        super.onActive();
        if (musicRemoteObject == null) {
            musicRemoteObject = MusicServiceAbility.get();
        }
        if (musicRemoteObject != null) {
            dataSync();
        }
    }

    /**
     * 启动服务
     */
    private void startService() {
        Intent startService = new Intent();
        Operation operation = new Intent.OperationBuilder()
            .withDeviceId("")
            .withBundleName(getBundleName())
            .withAbilityName(MusicServiceAbility.class.getName())
            .build();
        startService.setOperation(operation);
        startAbility(startService);
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        //我自己测试，JS卡片的图片刷新机制是当应用返回桌面时刷新才有效，所以在onInactive中更新卡片封面
        if (musicRemoteObject != null && musicRemoteObject.currentPosition != -1) {
            musicRemoteObject.updateCardCover();
        }
    }

    /**
     * layout初始化
     */
    private void initLayout() {
        List<PlayingIndex> playingIndices = DatabaseUtils.queryPlayingIndex(DatabaseUtils.getOrmContext(this));
        if (playingIndices != null && !playingIndices.isEmpty() && musicRemoteObject.currentPosition == -1) {
            musicRemoteObject.currentPosition = playingIndices.get(0).getOldIndex();
            musicRemoteObject.setSource();
            musicRemoteObject.playMusic();
        }

        btLast = (Button) findComponentById(ResourceTable.Id_button_last);
        btPlay = (Button) findComponentById(ResourceTable.Id_button_play);
        btNext = (Button) findComponentById(ResourceTable.Id_button_next);
        fixed = (Image) findComponentById(ResourceTable.Id_fixed);
        musicCover = (Image) findComponentById(ResourceTable.Id_music_cover);
        currentDuration = (Text) findComponentById(ResourceTable.Id_currentDuration);
        totalDuration = (Text) findComponentById(ResourceTable.Id_totalDuration);
        title = (Text) findComponentById(ResourceTable.Id_songName);
        singerName = (Text) findComponentById(ResourceTable.Id_singerName);
        playerAll = (Text) findComponentById(ResourceTable.Id_playerAll);
        number = (Text) findComponentById(ResourceTable.Id_number);
        slider = (Slider) findComponentById(ResourceTable.Id_progressBar);
        listContainer = (ListContainer) findComponentById(ResourceTable.Id_music_list);

        musicDataList = musicRemoteObject.getMusicList();
        musicCover.setCornerRadius(20);
        number.setText("(" + musicDataList.size() + ")");
        provider = new MusicListProvider(musicDataList, this);
        DirectionalLayoutManager layoutManager = new DirectionalLayoutManager();
        listContainer.setLayoutManager(layoutManager);
        listContainer.setItemProvider(provider);
        listContainer.enableScrollBar(Component.VERTICAL, true);
        listContainer.setScrollbarBackgroundColor(new Color(Color.argb(50, 0, 0, 0)));
        ClickEvent clickEvent = new ClickEvent();
        ValueChangeListener listener = new ValueChangeListener();
        btLast.setClickedListener(clickEvent);
        fixed.setClickedListener(clickEvent);
        btPlay.setClickedListener(clickEvent);
        btNext.setClickedListener(clickEvent);
        playerAll.setClickedListener(clickEvent);
        slider.setValueChangedListener(listener);
        slider.setProgressColor(new Color(Color.getIntColor("#9C9C9C")));
        endTouchElement();
        timer = new Timer();
        MusicServiceAbility.setCallback(this);
    }

    /**
     * 列表的点击事件
     */
    private void listClickEvent() {
        listContainer.setItemClickedListener((listContainer, component, position, id) -> {
            //根据点击列表position设置要播放的歌曲
            musicRemoteObject.currentPosition = position;
            musicRemoteObject.setSource();
        });
    }

    /**
     * 音乐播放后定时器刷新
     */
    private void playListener() {
        EventRunner mainEventRunner = EventRunner.getMainEventRunner();
        eventHandler = new EventHandler(mainEventRunner) {
            @Override
            protected void processEvent(InnerEvent event) {
                super.processEvent(event);
                double total = 0;
                if (musicRemoteObject.getPlayer() != null) {
                    total = musicRemoteObject.getPlayer().getDuration();
                }
                double current = event.param;
                double proportion = current / total * 100;
                String duration = DateToString(new Date(Math.min(Math.round(current), Math.round(total))), "mm:ss");
                String totalDurations = DateToString(new Date(Math.round(total)), "mm:ss");
                currentDuration.setText(duration);
                totalDuration.setText(totalDurations);
                long roundValue = Math.round(proportion);
                slider.setProgressValue(Math.toIntExact(roundValue));
            }
        };
        if (timer != null) {
            timer.purge();
            timer.cancel();
            timer = null;
        }
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (musicRemoteObject.getPlayer() != null && musicRemoteObject.getPlayer().isNowPlaying()) {
                    InnerEvent innerEvent = InnerEvent.get();
                    innerEvent.param = musicRemoteObject.getPlayer().getCurrentTime();
                    eventHandler.sendEvent(innerEvent);
                    btPlay.setBackground(new VectorElement(context, ResourceTable.Graphic_pause));
                }
            }
        }, 0, 100);
    }

    /**
     * 将毫秒转换为mm:ss
     *
     * @param source date
     * @param pattern 格式
     * @return 相应格式的时间
     */
    public static String DateToString(Date source, String pattern) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        return simpleDateFormat.format(source);
    }

    /**
     * 将毫秒转换为mm:ss
     *
     * @return 相应格式的时间
     */
    public static MusicListProvider getProvider() {
        return provider;
    }

    /**
     * 当从卡片进入时同步播放状态
     */
    private void dataSync() {
        //从卡片进入应用时同步数据
        if (musicRemoteObject != null && musicRemoteObject.currentPosition != -1) {
            if (musicRemoteObject.getPlayer() != null && musicRemoteObject.getPlayer().isNowPlaying()) {
                btPlay.setBackground(new VectorElement(context, ResourceTable.Graphic_pause));
            } else {
                btPlay.setBackground(new VectorElement(context, ResourceTable.Graphic_play));
            }
            if (provider != null) {
                listContainer.scrollTo(musicRemoteObject.currentPosition);
                int oldPosition = -1;
                List<PlayingIndex> indexList = DatabaseUtils.queryPlayingIndex(DatabaseUtils.getOrmContext(this));
                if (!indexList.isEmpty()) {
                    oldPosition = indexList.get(0).getOldIndex();
                }
                provider.updatePlayerState(oldPosition, musicRemoteObject.currentPosition, musicRemoteObject.getIsPlay());
            }
            title.setText(musicRemoteObject.getTitle());
            singerName.setText(musicRemoteObject.getSingerName());
            if (musicRemoteObject.getPixelMapCover() == null) {
                musicCover.setPixelMap(ResourceTable.Media_music);
            } else {
                musicCover.setPixelMap(musicRemoteObject.getPixelMapCover());
            }
        }
    }

    /**
     * 点击拖动条，放大拖动按钮
     */
    private void startTouchElement() {
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setRgbColor(RgbPalette.GRAY);
        shapeElement.setCornerRadius(100);
        shapeElement.setAlpha(255);
        shapeElement.setShape(ShapeElement.OVAL);
        shapeElement.setBounds(0, 0, 40, 40);//动态设置圆点宽高
        slider.setThumbElement(shapeElement);
    }

    /**
     * 松开拖动条，缩小拖动按钮
     */
    private void endTouchElement() {
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setRgbColor(RgbPalette.GRAY);
        shapeElement.setCornerRadius(100);
        shapeElement.setAlpha(255);
        shapeElement.setShape(ShapeElement.OVAL);
        shapeElement.setBounds(0, 0, 20, 20);//动态设置圆点宽高
        slider.setThumbElement(shapeElement);
        slider.invalidate();
    }

    @Override
    public void player() {
        ThreadUtil.runUI(() -> {
            title.setText(musicRemoteObject.getTitle());
            singerName.setText(musicRemoteObject.getSingerName());
            if (musicRemoteObject.getPixelMapCover() == null) {
                musicCover.setPixelMap(ResourceTable.Media_music);
            } else {
                musicCover.setPixelMap(musicRemoteObject.getPixelMapCover());
            }
        });
    }

    /**
     * 拖动条改变监听
     */
    class ValueChangeListener implements Slider.ValueChangedListener {
        @Override
        public void onProgressUpdated(Slider slider, int value, boolean fromUser) {
            if (fromUser) {
                //用户拖动时改变当前播放进度显示
                float total = musicRemoteObject.getPlayer().getDuration();
                float proportion = total / 100 * value;
                String values = DateToString(new Date((long) proportion), "mm:ss");
                updateValue = value;
                currentDuration.setText(values);
            }
        }

        @Override
        public void onTouchStart(Slider slider) {
            startTouchElement();

            //用户开始拖动时关闭歌曲进度监听，否则进度条会来回跳动
            timer.cancel();
            timer = null;
        }

        @Override
        public void onTouchEnd(Slider slider) {
            endTouchElement();

            //结束拖动时，更新歌曲播放进度并重新设置监听
            float total = musicRemoteObject.getPlayer().getDuration();
            float proportion = total / 100 * updateValue;
            musicRemoteObject.getPlayer().rewindTo((long) (proportion * 1000));
            playListener();
        }
    }

    /**
     * 封装button的点击事件
     */
    class ClickEvent implements Component.ClickedListener {
        @Override
        public void onClick(Component component) {
            switch (component.getId()) {
                case ResourceTable.Id_button_last:
                    musicRemoteObject.lastMusic();
                    break;
                case ResourceTable.Id_button_play:
                    if (musicRemoteObject.getPlayer() == null) {
                        musicRemoteObject.initPlayer(context);
                    }
                    if (musicRemoteObject.getIsPlay()) {
                        btPlay.setBackground(new VectorElement(context, ResourceTable.Graphic_play));
                    } else {
                        btPlay.setBackground(new VectorElement(context, ResourceTable.Graphic_pause));
                    }
                    musicRemoteObject.playMusic();
                    break;
                case ResourceTable.Id_button_next:
                    musicRemoteObject.nextMusic();
                    break;
                case ResourceTable.Id_fixed:
                    listContainer.scrollTo(musicRemoteObject.currentPosition == -1
                        ? 0
                        : musicRemoteObject.currentPosition);
                    break;
                case ResourceTable.Id_playerAll:
                    musicRemoteObject.playMusic();
                    break;
            }
        }
    }

    @Override
    protected void onStop() {
        super.onStop();

        //关闭服务
        Intent stopService = new Intent();
        Operation operation = new Intent.OperationBuilder()
            .withDeviceId("")
            .withBundleName(getBundleName())
            .withAbilityName(MusicServiceAbility.class.getName())
            .build();
        stopService.setOperation(operation);
        stopAbility(stopService);
        timer.cancel();
        timer = null;
        eventHandler.removeAllEvent();
    }
}
